/**
 * @说明 用于对齐 fabrice元素（适用于v1.7*版本的fabric.js库）
 *
 * @param {canvas} 参数说明：需要传入 new fabric.Canvas() 的那个对象
 * @param {alignparam} 参数说明：
 *  @param top 上对齐（默认值，已实现）
 *  @param left 左对齐（已实现）
 *  @param botton 底对齐（已实现）
 *  @param right 右对齐（已实现）
 *  @param horizontalC 水平居中对齐（已实现）
 *  @param verticalC 垂直居中对齐（已实现）
 *  @param horizontalA 水平平均分布（已实现）
 *  @param verticalA 垂直平均分布（已实现）
 *
 * @author zkp
 * @time 2019.6.13 - 2019.6.14
 *
 *
 * 问题已经处理...lxw
 */
const fabricItemAlign = (canvas, alignparam = "top") => {
  // 实现方案一：通过计算，对顶掉偏差（这里框架内部计算还是有很大的问题的,不可控）
  // 规定术语说明，选中的好几个元素，最外层的那一个大的元素称之为 Z
  // canvas._activeGroup 表示 Z 也就是选中之后的最大的一层
  // ARRAY 为选中的所有元素

  // v3.* 兼容性方案（下面代码写的是v1.7*版本的方案）
  // ①：canvas._activeGroup._objects 换为 canvas.getActiveObjects()
  // ②：canvas._activeGroup 换为 canvas._activeObject

  let ARRAY = canvas.getActiveObjects(); //canvas._activeGroup._objects;
  let activeObject = canvas._activeObject; //canvas._activeGroup

  //选中一个不要处理
  if (ARRAY.length <= 1) return;

  //console.log("ARRAY", ARRAY, activeObject);

  // 顶对齐
  if (alignparam === "top") {
    // 是以选中框 为相对位置进行计算的（顶对齐就是 top为 0 ，左对齐就是 left 0）
    // 下面就是计算 剩余一个轴 相对于 选择框的相对位置
    ARRAY.forEach(item => {
      // 顶对齐算法：top为零表示 依据选中框顶部对齐， left 为 选中点每一项的
      item.set({
        top: 0 - activeObject.height * 0.5
      });
    });
  }

  // 左对齐
  if (alignparam === "left") {
    // 是以选中框 为相对位置进行计算的（顶对齐就是 top为 0 ，左对齐就是 left 0）
    // 下面就是计算 剩余一个轴 相对于 选择框的相对位置
    ARRAY.forEach(item => {
      item.set({
        left: -activeObject.width / 2
      });
    });
  }

  // 右对齐
  if (alignparam === "right") {
    // top公式：与 左对齐一致
    // left公式：坐标要以 Z 的宽度为计算，并减去元素本身的宽度
    ARRAY.forEach(item => {
      //console.log(activeObject);
      item.set({
        left: activeObject.width * 0.5 - item.width
      });
    });
  }

  // 底对齐
  if (alignparam === "bottom") {
    // top公式：与 左对齐一致
    // left公式：与 上对齐一致
    ARRAY.forEach(item => {
      // 顶对齐算法：top为零表示 依据选中框顶部对齐， left 为 选中点每一项的
      item.set({
        top: activeObject.height * 0.5 - item.height
      });
    });
  }

  // 水平居中对齐
  if (alignparam === "horizontalC") {
    // top公式：(Z.heiht - 每一项的元素的.height) 其实就是这个元素相对于 Z 中线的一个居中位置（和CSS定位居中对齐一个原理）
    // left公式：保持位置相对不动
    ARRAY.forEach(item => {
      item.set({
        left: 0 - item.width * 0.5
      });
    });
  }

  // 垂直居中对齐
  if (alignparam === "verticalC") {
    // top公式：保持位置相对不动
    // left公式：(Z.heiht - 每一项的元素的.height)
    ARRAY.forEach(item => {
      item.set({
        top: 0 - item.height * 0.5
      });
    });
  }

  // 水平平均分布
  if (alignparam === "horizontalA") {
    // 前置：需要按照 ARRAY 每一项的 aCoords.tl.x 进行从小到大排列，因为开始结束位置可能不一样
    // 注意：sort方法排序改变的是原有的数组不生成副本
    ARRAY.sort((a, b) => {
      return a.aCoords.tl.x - b.aCoords.tl.x;
    });

    // 水平等差间距：
    let count = 0;
    ARRAY.forEach(item => {
      count += item.width;
    });
    let es = (activeObject.width - count) / (ARRAY.length - 1);

    let sefNum = 0; // 记录中间过程值
    let sefNumOne = true; // 判定

    // console.log('水平等差间距是：', es)

    for (let i = 0, len = ARRAY.length; i < len; i++) {
      // 等分排列 开始和结尾不变
      if (i !== 0 && i !== len - 1) {
        if (sefNumOne) {
          // 第二个的计算规则是：第一个的长度 + 等差间距
          sefNum += ARRAY[i - 1].width + es;
          sefNumOne = false;
        } else {
          // 其他项的计算规则是：sefNum（这个相当于前一个的 left值） + 前一个的宽度 + 等差间距
          sefNum += es + ARRAY[i - 1].width;
        }

        //console.log("sefNum", sefNum);

        // top规则：保持相对位置不变
        // left规则：采用 sefNum 的值
        ARRAY[i].set({
          //   top:
          //     ARRAY[i].aCoords.tl.y -
          //     activeObject.aCoords.tl.y -
          //     activeObject.height * 0.5,
          left: sefNum - activeObject.width * 0.5
        });
      }
    }
  }

  // 垂直平均分布
  if (alignparam === "verticalA") {
    // 前置：需要按照 ARRAY 每一项的 aCoords.tl.x 进行从小到大排列，因为开始结束位置可能不一样
    // 注意：sort方法排序改变的是原有的数组不生成副本
    ARRAY.sort((a, b) => {
      return a.aCoords.tl.y - b.aCoords.tl.y;
    });

    // 垂直等差间距：
    let count = 0;
    ARRAY.forEach(item => {
      count += item.height;
    });
    let es = (activeObject.height - count) / (ARRAY.length - 1);

    let sefNum = 0; // 记录中间过程值
    let sefNumOne = true; // 判定

    // console.log('垂直等差间距：', es)

    for (let i = 0, len = ARRAY.length; i < len; i++) {
      // 等分排列 开始和结尾不变
      if (i !== 0 && i !== len - 1) {
        if (sefNumOne) {
          // 第二个的计算规则是：第一个的高度 + 宽度等差间距
          sefNum += ARRAY[i - 1].height + es;
          sefNumOne = false;
        } else {
          // 其他项的计算规则是：sefNum（这个相当于前一个的 top值） + 前一个的高度 + 宽度等差间距
          sefNum += es + ARRAY[i - 1].height;
        }

        // top规则：采用 sefNum 的值
        // left规则：保持相对位置不变
        ARRAY[i].set({
          top: sefNum - activeObject.height * 0.5
          //   left:
          //     ARRAY[i].aCoords.tl.x -
          //     activeObject.aCoords.tl.x -
          //     activeObject.width * 0.5
        });
      }
    }
  }

  // 其他对齐规则拓展 ......

  canvas.renderAll(); // 重新渲染
};

export default fabricItemAlign;
